package dm

import (
	"fmt"
	ole "github.com/go-ole/go-ole"
	"github.com/go-ole/go-ole/oleutil"
	"plan_go/config"
	"sync"
	"syscall"
	"unsafe"
)

var (
	dmReg32         = syscall.NewLazyDLL(config.GetPath("dm/dmReg.dll"))
	procSetDllPathA = dmReg32.NewProc("SetDllPathA")
	procSetDllPathW = dmReg32.NewProc("SetDllPathW")
	Dm              *DmSoft
	DmObjMap        = make(map[string]*DmSoft)
)

func GetDm(objName string) *DmSoft {
	if nil == DmObjMap[objName] {
		SetGlobalDm(objName)
	}
	return DmObjMap[objName]
}

// DmSoft ...
type DmSoft struct {
	dm       *ole.IDispatch
	IUnknown *ole.IUnknown
	//状态管理
	wg sync.WaitGroup
}

// New return *DmSoft.DmSoft
func NewDmDll() (dm *DmSoft, err error) {
	var com DmSoft
	// 创建对象
	ole.CoInitialize(0)
	com.IUnknown, err = oleutil.CreateObject("dm.dmsoft")
	if err != nil {
		return nil, err
	}
	// 查询接口
	com.dm, err = com.IUnknown.QueryInterface(ole.IID_IDispatch)
	if err != nil {
		return nil, err
	}
	com.wg = sync.WaitGroup{}
	return &com, nil
}

func SetGlobalDm(objName string) {
	println("大漠插件路径: " + config.GetPath("dm/dm.dll"))
	SetDllPathW(config.GetPath("dm/dm.dll"), 0)
	dm, err := NewDmDll()
	if err != nil {
		panic(err)
	}
	DmObjMap[objName] = dm
	fmt.Printf("当前插件版本:%s\n,", dm.Ver())
	//注册vip
	reg := dm.Reg("xf30557fc317f617eead33dfc8de3bdd4ab9043", "xc72ddc2uks0jv7")
	println(fmt.Sprintf("注册插件结果: %d\n", reg))
	if 1 != reg {
		panic("大漠对象创建失败")
	}
	println(objName + "大漠对象创建成功")
}

// SetDllPathA Ascii
func SetDllPathA(path string, mode int) bool {
	var _p0 *uint16
	_p0, _ = syscall.UTF16PtrFromString(path)
	ret, _, _ := syscall.Syscall(procSetDllPathA.Addr(), 2, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
	return ret != 0
}

// Release 大漠释放
func (com *DmSoft) Release() {
	com.IUnknown.Release()
	com.dm.Release()
	ole.CoUninitialize()
}

// SetDllPathW Unicode
func SetDllPathW(path string, mode int) bool {
	var _p0 *uint16
	_p0, _ = syscall.UTF16PtrFromString(path)
	ret, _, _ := syscall.Syscall(procSetDllPathW.Addr(), 2, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0)
	return ret != 0
}

func ExitDm() {
	//释放大漠模块
	Dm.Release()
	println("已释放大漠模块!")
}
